package client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import java.util.Collection;
import java.util.Iterator;


import actions.ActionFactory;

import net.solosky.maplefetion.ClientState;
import net.solosky.maplefetion.FetionClient;
import net.solosky.maplefetion.LoginState;
import net.solosky.maplefetion.NotifyEventAdapter;
import net.solosky.maplefetion.bean.Buddy;
import net.solosky.maplefetion.bean.Cord;
import net.solosky.maplefetion.bean.Group;
import net.solosky.maplefetion.bean.Member;
import net.solosky.maplefetion.bean.Message;
import net.solosky.maplefetion.bean.Presence;
import net.solosky.maplefetion.bean.Relation;
import net.solosky.maplefetion.bean.VerifyImage;
import net.solosky.maplefetion.client.dialog.ChatDialogProxy;
import net.solosky.maplefetion.client.dialog.GroupDialog;
import net.solosky.maplefetion.event.ActionEvent;
import net.solosky.maplefetion.event.ActionEventType;
import net.solosky.maplefetion.event.action.ActionEventListener;
import net.solosky.maplefetion.event.action.FailureEvent;
import net.solosky.maplefetion.event.action.success.SendChatMessageSuccessEvent;
import net.solosky.maplefetion.event.notify.ImageVerifyEvent;
import net.solosky.maplefetion.net.AutoTransferFactory;
import net.solosky.maplefetion.store.FetionStore;
import net.solosky.maplefetion.store.SimpleFetionStore;
import net.solosky.maplefetion.util.SingleExecutor;
import net.solosky.maplefetion.util.StringHelper;
import net.solosky.maplefetion.util.ThreadTimer;
/**
 * 
 * @author cjcj cj.yangjun@gmail.com
 * @date 2011-01-10
 *
 */
public class Client extends NotifyEventAdapter{
	/**
	 * the fetionclient of maplefetion framework
	 */
	private FetionClient client;

	/**
	 * 当前需要处理的验证码事件,这里只能处理一个，如果要处理多个，则需建立验证码处理队列
	 */
	private ImageVerifyEvent verifyEvent;
	
	
	private BufferedReader reader;
	private BufferedWriter writer;

	
	
	//private AtomicInteger state=new AtomicInteger();
	
	private String robotUser="";
	private String robotPw="";
	
	public Client(){
		reader=new BufferedReader(new InputStreamReader(System.in));
		writer=new BufferedWriter(new OutputStreamWriter(System.out));
		writeLine("Input your Mobile/FetionID:");
		robotUser=readLine();
		writeLine("Input your Password:");
		robotPw=readLine();
		client = new FetionClient(robotUser, robotPw,
				this, 
				new AutoTransferFactory(),
				new SimpleFetionStore(), 
				new ThreadTimer(),
				new SingleExecutor());
		
		client.enableGroup(false);
		client.login(Presence.ONLINE);
		
	}
	
	public void loginStateChanged(LoginState state)
    {
	    switch (state)
        {	
        case	SEETING_LOAD_DOING:		//加载自适应配置
        	writeLine("获取自适应系统配置...");
	    	break;
        case	SSI_SIGN_IN_DOING:		//SSI登录
        	writeLine("SSI登录...");
	    	break;
        case	SIPC_REGISTER_DOING:		//注册SIPC服务器
        	writeLine("服务器验证...");
	    	break;
        case	GET_CONTACTS_INFO_DOING:	//获取联系人信息
        	writeLine("获取联系人...");
	    	break;
        case	GET_GROUPS_INFO_DOING:	//获取群消息
        	writeLine("获取群信息...");
	    	break;
        case	GROUPS_REGISTER_DOING:	//注册群
        	writeLine("群登录...");
	    	break;
        	
        //以下是成功信息，不提示
        case	SETTING_LOAD_SUCCESS:
        case	SSI_SIGN_IN_SUCCESS:
        case	SIPC_REGISGER_SUCCESS:
        case	GET_CONTACTS_INFO_SUCCESS:
        case	GET_GROUPS_INFO_SUCCESS:
        case	GROUPS_REGISTER_SUCCESS:
        	break;


        case LOGIN_SUCCESS:
        	writeLine("登录成功");
        	client.updateState(ClientState.ONLINE);
        	run();
        	break;	
        case SSI_NEED_VERIFY:
        case SSI_VERIFY_FAIL:
        	if(state==LoginState.SSI_NEED_VERIFY)
        		writeLine("需要验证, 请输入目录下的[verify.png]里面的验证码:");
        	else
        		writeLine("验证码验证失败，刷新验证码中...");
	        break;

        case SSI_CONNECT_FAIL:
        	writeLine("SSI连接失败!");
        	break;
        	
        case SIPC_TIMEOUT:
        	writeLine("登陆超时！");
        	break;
        	
        case SSI_AUTH_FAIL:
        	writeLine("用户名或者密码错误!");
        	break;
        	
        case SSI_ACCOUNT_SUSPEND:
        	writeLine("你已经停机，请缴费后再使用飞信。");
        	break;
        	
        default:
        	writeLine("其他状态:"+state.name());
	        break;
        }
	    
    }  
	
    
    private String readLine()
    {
    	try {
    		String cmd=this.reader.readLine();
    		writeLine("");
	        return cmd;
        } catch (IOException e) {
	        e.printStackTrace();
        }
        return null;
    }
    
    
    /**
     * 打印一行字符
     */
    public void writeLine(String s)
    {
    	
    	try {
    		
    		this.writer.append(s);
    		this.writer.append('\n');
    		this.writer.append("cmd>>");
	        this.writer.flush();
        } catch (IOException e) {
	        e.printStackTrace();
        }
    }
        
    private void run(){
    	while(true){
    		String cmd=readLine();
    		if(cmd.equals("exit")){
    			new Logout().run();
    		}else if(cmd.equals("list")){
    			new ListAllBuddy().run();
    		}else if(cmd.startsWith("sa")){
    			new SmsAllBuddy().run(cmd.substring(2));
    		}else if(cmd.endsWith("login")){
    			new Login().run();
    		}else{
    			writeLine("Unknow Command");
    		}
    	}
    }
    @Override
    public void clientStateChanged(ClientState state)
    {
	    switch (state)
        {
        case OTHER_LOGIN:
        	writeLine("你已经从其他客户端登录。");
        	
	        break;
        case CONNECTION_ERROR:
        	writeLine("客户端连接异常");
        	client.login(Presence.ONLINE);
        	client.updateState(ClientState.ONLINE);
	        break;
        case DISCONNECTED:
        	writeLine("服务器关闭了连接");
        	break;
        case LOGOUT:
        	writeLine("已经退出。。");
        	break;
        case ONLINE:
        	writeLine("当前是在线状态。");
        	break;
        	
        default:
	        break;
        }
    }
    
    // ###############################override:recieve msg ####################
    @Override
    public void buddyPresenceChanged(Buddy b)
    {
    	if(b.getPresence().getValue()==Presence.ONLINE) {
    		writeLine("[系统通知]:"+b.getDisplayName()+" 上线了。");
        	
    	}else if(b.getPresence().getValue()==Presence.OFFLINE){
    		writeLine("[系统通知]:"+b.getDisplayName()+" 下线了。");
        	
    	}
	    
    }
    @Override
    public void groupMessageRecived(Group group, Member from, Message message, GroupDialog dialog)
    {
    	writeLine("[群消息] 群 "+group.getName()+" 里的 "+from.getDisplayName()+" 说："+message.getText());
    }

    @Override
    public void buddyMessageRecived(Buddy from, Message message, ChatDialogProxy dialog)
    {
    	try {
    	if(from.getRelation()==Relation.BUDDY){
    		writeLine("[好友消息]"+from.getDisplayName()+" 说:"+message.getText());
    		String response=ActionFactory.doCommand(from,message.getText());
    		
    		/**
    		 * transfer all message,which are not command,to your cell phone
    		 */
    		//sms2Cell(from,response);
    		sms2Cell(client.getFetionUser(), response);
    		
    	}
    	else 
    		writeLine("[陌生人消息]"+from.getDisplayName()+" 说:"+message.getText());
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    	
    }

    // #########################Verify #########################
	  protected void imageVerify(final VerifyImage verifyImage, final String verifyReason,
	            final String verifyTips, final ImageVerifyEvent event)
	    {
	    	
	    	saveImage(verifyImage.getImageData());
	    	if(client.getState()==ClientState.LOGGING) {
				System.out.print("当前登录过程需要验证，原因【"+verifyReason+"】,请输入当前目录下图片[verify.jpg]中的验证码：");
				String line =readLine();
				verifyImage.setVerifyCode(line);
				client.processVerify(event);
	    	}else {
	    		writeLine("当前操作需要验证,原因:【"+verifyReason+"】。\n请使用verify命令输入当前目录下图片[verify.jpg]中的验证码(如verify 123abc).");
	    		verifyEvent = event;
	    	}
	    }
	  
	  /**
	     * 保存验证图片
	     * @param img
	     */
	    private void saveImage(byte[] img)
	    {
	    	try {
	    		FileOutputStream out = new FileOutputStream(new File("verify.png"));
	        	out.write(img);
	        	out.close();
	        } catch (Exception e) {
	        }
	    }
	    public static void main(String args[]){
	    	new Client();
	    }
	    
	    
	    private void logout(){
	    	ActionFactory.shutdown();
	    }
	    class Logout{
	    	public void run(){
	    		logout();
	    		client.logout();
	    		System.exit(0);
	    	}
	    }
	    class ListAllBuddy{
	    	/**
		     * 显示所有用户列表
		     */
		    public void run()
		    {
		    	writeLine("\n=================================");
		    	writeLine("所有好友列表");
		    	writeLine("-------------------------------");
		    	writeLine("#ID\t好友昵称\t在线状态\t个性签名");
		    	FetionStore store = client.getFetionStore();
		    	Iterator<Cord> it = store.getCordList().iterator();
		    	int id=0;
		    	
		    	//分组显示好友
		    	while(it.hasNext()) {
		    		Cord cord = it.next();
		    		id = cord(cord.getId(),cord.getTitle(),id, store.getBuddyListByCord(cord));
		    	}
		    	id = cord(-1,"默认分组", id, store.getBuddyListWithoutCord());
		    }
		    /**
		     * 显示一个组的用户
		     */
		    public int cord(int cordId, String name,int startId,Collection<Buddy> buddyList)
		    {
		    	Iterator<Buddy> it = buddyList.iterator();
		    	Buddy buddy = null;
		    	writeLine("\n-------------------------------");
		    	writeLine("【"+cordId+"::"+name+"】");
		    	writeLine("-------------------------------");
		    	if(buddyList.size()==0) {
		    		writeLine("暂无好友。。");
		    	}
				while(it.hasNext()) {
					buddy = it.next();
					//this.buddymap.put(Integer.toString(startId), buddy.getUri());
					String impresa = buddy.getImpresa();
					writeLine(Integer.toString(startId)+" "+buddy.getRelation()+" "+buddy.getDisplayName()+"\t"
							+buddy.getDisplayPresence()
							+"\t"+(impresa==null?"":impresa));
					startId++;
				}
				return startId;
		    }
	    }
	     class SmsAllBuddy{
	    	public void run(String msg){
	    		FetionStore store = client.getFetionStore();
		    	Iterator<Cord> cordIt;
		    	Iterator<Buddy> buddyIt;
		    	cordIt=store.getCordList().iterator();
		    	while(cordIt.hasNext()){
		    		Cord cord=cordIt.next();
		    		buddyIt=store.getBuddyListByCord(cord).iterator();
		    		while(buddyIt.hasNext()){
		    			
		    			sms2Cell(buddyIt.next(),msg);
		    		}
		    	}
		    	// get buddy without cord
		    	buddyIt=store.getBuddyListWithoutCord().iterator();
		    	while(buddyIt.hasNext()){
		    		sms2Cell(buddyIt.next(),msg);
		    	}
	    	}
	    }
	     class Login{
	    	 public void run(){
	    		 client.login(Presence.HIDEN);
	    		 client.updateState(ClientState.ONLINE);
	    	 }
	     }
	    
	    //######################## send #######################
	    
	    /**
	     * 发送手机短信消息
	     */
	    public void sms2Cell(final Buddy buddy, final String message)
	    {
	    	if(buddy!=null) {
	    		this.client.sendSMSMessage(buddy, Message.wrap(message), new ActionEventListener(){
					public void fireEevent(ActionEvent event)
					{
						if(event.getEventType()==ActionEventType.SUCCESS){
							writeLine("提示：发送给"+buddy.getDisplayName()+" 的短信发送成功！");
						}else{
							writeLine("[系统消息]:你发给 "+buddy.getDisplayName()+" 的短信  "+message+" 发送失败！");
						}
					}
				});
	    	}else {
	    		writeLine("找不到这个好友，请检查你的输入！");
	    	}
	    }
}
